package com.sjme.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.constant.RedisKey;
import com.sjme.domain.commonService.SelectOption;
import com.sjme.domain.commonService.OptionGroup;
import com.sjme.domain.commonService.dto.OptionGroupDto;
import com.sjme.domain.commonService.dto.SelectOptionDto;
import com.sjme.service.CommonService;
import com.sjme.service.IOptionGroupService;
import com.sjme.service.ISelectOptionService;
import com.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.constant.CommonConstant.OptionConstant.*;


@Slf4j
@Service
public class CommonServiceImpl implements CommonService {
    @Autowired
    private ISelectOptionService selectOptionService;
    @Autowired
    private IOptionGroupService optionGroupService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public Result getSelectOptions(List<String> optionGroupKeys) {
        List<SelectOption> selectOptions = new ArrayList<>();
        // 先根据条件从缓存中获取，若缓存中不存在，再查库构建缓存并返回数据
        List<String> optionGroupKeysParam = optionGroupKeys.stream().map(item -> RedisKey.Interview.OPTION_KEY_PREFIX + item).collect(Collectors.toList());
        List<String> interviewOptionsCache = redisTemplate.opsForValue().multiGet(optionGroupKeysParam);
        // 判断缓存是否全部命中（列表非空且所有元素都不为null）
        if (interviewOptionsCache != null && interviewOptionsCache.stream().noneMatch(Objects::isNull)) {
            List<SelectOption> finalSelectOptions = selectOptions;
            interviewOptionsCache.stream().forEach(item -> {
                List<SelectOption> options = JSONObject.parseArray(item, SelectOption.class);
                finalSelectOptions.addAll(options);
            });
        }else {
            // 查库
            LambdaQueryWrapper<SelectOption> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(SelectOption::getOptionGroupKey, optionGroupKeys);
            selectOptions = selectOptionService.list(queryWrapper);
            // 重建缓存
            Map<String, String> selectOptionsMap = new HashMap<>();
            selectOptions.stream().collect(Collectors.groupingBy(SelectOption::getOptionGroupKey)).forEach((key, value) -> {
                selectOptionsMap.put(RedisKey.Interview.OPTION_KEY_PREFIX + key,JSONObject.toJSONString(value));
            });
            redisTemplate.opsForValue().multiSet(selectOptionsMap);
        }
        return Result.success(selectOptions);
    }

    @Override
    public IPage<OptionGroup> queryOptionGroup(OptionGroupDto optionGroup) {
        // 获取参数
        String groupDesc = optionGroup.getGroupDesc();
        String groupKey = optionGroup.getGroupKey();
        Integer status = optionGroup.getStatus();
        String startTime = optionGroup.getStartTime();
        String endTime = optionGroup.getEndTime();
        // 构建条件
        IPage<OptionGroup> page = new Page<>();
        LambdaQueryWrapper<OptionGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(groupDesc), OptionGroup::getGroupDesc, groupDesc);
        queryWrapper.like(StringUtils.isNotBlank(groupKey), OptionGroup::getGroupKey, groupKey);
        queryWrapper.eq(status != null, OptionGroup::getStatus, status);
        queryWrapper.gt(StringUtils.isNotBlank(startTime),OptionGroup::getCreateTime, startTime);
        queryWrapper.le(StringUtils.isNotBlank(endTime),OptionGroup::getCreateTime, endTime);
        queryWrapper.orderByAsc(OptionGroup::getCreateTime);
        // 查询
        optionGroupService.page(page, queryWrapper);
        return page;
    }

    @Override
    public boolean addOptionGroup(OptionGroup optionGroup) {
        return optionGroupService.save(optionGroup);
    }

    @Override
    public String deleteOptionGroup(List<String> optionGroupKeys) {
        // 查询组别下是否存在字典数据，若存在，则不能删除
        int count = selectOptionService.count(Wrappers.<SelectOption>lambdaQuery().in(SelectOption::getOptionGroupKey, optionGroupKeys));
        if (count > 0) {
            return EXISTS_SELECT_OPTION;
        }
        if (optionGroupService.remove(Wrappers.<OptionGroup>lambdaQuery().in(OptionGroup::getGroupKey, optionGroupKeys))){
            return DELETE_OPTION_GROUP_SUCCESS;
        }
        return DELETE_OPTION_GROUP_FAIL;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateOptionGroup(OptionGroup optionGroup) {
        optionGroup.setUpdateTime(LocalDateTime.now());
        String groupKey = optionGroup.getGroupKey();
        // 查询修改的组别key是否已存在，且判断是否为组别的数据，若是则不修改关联字段数据。
        // 若不是当前组别数据，则说明修改后的组别key与其他组别key相同，则禁止修改。
        boolean isCurrentDataUpdate = false;
        OptionGroup optionGroupInfo = optionGroupService.getOne(Wrappers.<OptionGroup>lambdaQuery().eq(OptionGroup::getGroupKey, groupKey));
        if (optionGroupInfo != null && optionGroupInfo.getId().equals(optionGroup.getId())) {
            // 修改的是当前数据
            isCurrentDataUpdate = true;
        }else if (optionGroupInfo != null){
            // 修改的组别key已有其他组别数据使用
            return EXISTS_OPTION_GROUP_KEY;
        }

        // 查询组别下关联的字典数据 并更新字典数据的组别Key
        if (!isCurrentDataUpdate) {
            // 根据id获取原组别key，然后根据组别key查出关联的字典数据
            String oldGroupKey = optionGroupService.getOne(Wrappers.<OptionGroup>lambdaQuery().eq(OptionGroup::getId, optionGroup.getId())).getGroupKey();
            List<SelectOption> selectOptionList = selectOptionService.list(Wrappers.<SelectOption>lambdaQuery().eq(SelectOption::getOptionGroupKey, oldGroupKey));
            List<SelectOption> collect = selectOptionList.stream().map(item -> item.setOptionGroupKey(groupKey)).collect(Collectors.toList());
            // 更新关联的字典数据的组别key
            selectOptionService.updateBatchById(collect);
        }
        // 修改组别数据
        optionGroupService.updateById(optionGroup);
        return UPDATE_OPTION_GROUP_SUCCESS;
    }

    @Override
    public IPage<SelectOption> querySelectOption(SelectOptionDto selectOption) {
        // 获取参数
        String groupKey = selectOption.getOptionGroupKey();
        String label = selectOption.getLabel();
        String value = selectOption.getValue();
        Integer status = selectOption.getStatus();
        String startTime = selectOption.getStartTime();
        String endTime = selectOption.getEndTime();
        // 构建条件
        IPage<SelectOption> page = new Page<>();
        LambdaQueryWrapper<SelectOption> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(groupKey), SelectOption::getOptionGroupKey, groupKey);
        queryWrapper.like(StringUtils.isNotBlank(label), SelectOption::getLabel, label);
        queryWrapper.eq(StringUtils.isNotBlank(value), SelectOption::getValue, value);
        queryWrapper.eq(status != null, SelectOption::getStatus, status);
        queryWrapper.gt(StringUtils.isNotBlank(startTime),SelectOption::getCreateTime, startTime);
        queryWrapper.le(StringUtils.isNotBlank(endTime),SelectOption::getCreateTime, endTime);
        queryWrapper.orderByAsc(SelectOption::getSort).orderByAsc(SelectOption::getCreateTime);
        // 查询
        selectOptionService.page(page, queryWrapper);
        return page;
    }

    @Override
    public boolean addSelectOption(SelectOption selectOption) {
        return selectOptionService.save(selectOption);
    }

    @Override
    public boolean deleteSelectOption(List<String> selectOptionIds) {
        return selectOptionService.removeByIds(selectOptionIds);
    }

    @Transactional
    @Override
    public boolean updateSelectOption(SelectOption selectOption) {
        if (selectOption.getIsDefault()) {
            // 重置原默认值选项
            SelectOption removeDefaultData = new SelectOption();
            removeDefaultData.setIsDefault(false);
            selectOptionService.update(removeDefaultData,Wrappers.<SelectOption>lambdaUpdate()
                    .eq(SelectOption::getOptionGroupKey, selectOption.getOptionGroupKey())
                    .eq(SelectOption::getIsDefault,true));
        }
        return selectOptionService.updateById(selectOption);
    }
}
